﻿using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using ZhuXingFamilys.Help;
using RevitAddInDeployer;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.IO;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.DB.Structure;
using ZhuXingFamilys.MainViewModel;

namespace ZhuXingFamilys.MainFamilyView
{
    public class LoadFamily : IExternalEventHandler
    {
        public string FamilyFileName { set; get; }
        public string LoadButtonCont { set; get; }
        public string FamilyFileCategory { set; get; }
        public string FamilyCategoryName { get; set; }
        public string FamilyNodeID { get; set; }
        public string FamilyID { get; set; }
        public List<FamilyProperty> FamilyProperties { get; set; }
        public void Execute(UIApplication app)
        {

            UIDocument uidoc = app.ActiveUIDocument;
            Document doc = uidoc.Document;

            Family family = null;

            if (FamilyFileCategory == "1" && LoadButtonCont == "载入项目")
            {
                // 过滤当前文档是否存在该族
                FilteredElementCollector collector = new FilteredElementCollector(doc);
                collector.OfClass(typeof(Family));//.FirstOrDefault(x => x.Name == FamilyFileName);
                IList<Element> CollectorList = collector.ToElements();
                if (CollectorList == null)
                {
                }
                foreach (var elem in CollectorList)
                {
                    var familyItem = elem as Family;
                    // str是要载入族的名称
                    if (familyItem.Name == FamilyFileName)
                    {
                        family = familyItem;
                        break;
                    }
                }
                // 如果未载入过，则载入该族
                if (family == null)
                {
                    Transaction transaction = new Transaction(doc); //事务
                    transaction.Start("载入族");
                    string Path = Set.settingaddress("Setup.ini");

                    //string FullPath = Path + "\\" + FamilyCategoryName + "\\" + FamilyFileName + ".rfa";
                    //if (!Directory.Exists(Path + "\\" + FamilyCategoryName))
                    //    Directory.CreateDirectory(Path + "\\" + FamilyCategoryName);
                    //string adss = FullPath;
                    //string ftpadss = FtpHelper.path + FamilyCategoryName + "\\" + FamilyFileName + ".rfa";

                    string FullPath = Path + "\\" + FamilyNodeID.Replace(" ", "") + "\\" + FamilyFileName + ".rfa";
                    if (!File.Exists(FullPath))
                    {
                        if (!Directory.Exists(Path + "\\" + FamilyNodeID.Replace(" ", "")))
                            Directory.CreateDirectory(Path + "\\" + FamilyNodeID.Replace(" ", ""));
                        string adss = FullPath;
                        string ftpadss = FtpHelper.path + FamilyNodeID.Replace(" ", "") + "\\" + FamilyFileName + ".rfa";
                        FtpHelper.Download(adss, ftpadss);
                    }

                    bool b = doc.LoadFamily(FullPath, out family); //载入族
                    if (!b)
                    {
                        MessageBox.Show("载入族失败");
                        return;
                    }
                    transaction.Commit();
                    //MessageBox.Show("载入族成功");
                }
            }
            //系统族
            if (FamilyFileCategory == "0" && LoadButtonCont == "载入项目")
            {
                ElementType targetType = new FilteredElementCollector(doc)
                .OfClass(typeof(ElementType))
                .FirstOrDefault(x => x.Name == FamilyFileName) as ElementType;
                if (targetType == null)
                {
                    string RvtFilePath = MainFamilyView.FileAddress;

                    //string RvtFullPath = RvtFilePath + "\\" + FamilyCategoryName + "\\" + FamilyFileName + ".rvt";
                    //if (!Directory.Exists(RvtFilePath + "\\" + FamilyCategoryName))
                    //    Directory.CreateDirectory(RvtFilePath + "\\" + FamilyCategoryName);
                    //string adss = RvtFullPath;
                    //string ftpadss = FtpHelper.path + FamilyCategoryName + "\\" + FamilyFileName + ".rvt";

                    string RvtFullPath = RvtFilePath + "\\" + FamilyNodeID.Replace(" ", "") + "\\" + FamilyFileName + ".rvt";
                    if (!Directory.Exists(RvtFilePath + "\\" + FamilyNodeID.Replace(" ", "")))
                        Directory.CreateDirectory(RvtFilePath + "\\" + FamilyNodeID.Replace(" ", ""));
                    string adss = RvtFullPath;
                    string ftpadss = FtpHelper.path + FamilyNodeID.Replace(" ", "") + "\\" + FamilyFileName + ".rvt";

                    FtpHelper.Download(adss, ftpadss);

                    Document docs = app.Application.OpenDocumentFile(RvtFullPath);
                    FilteredElementCollector collectors = new FilteredElementCollector(docs);
                    if (collectors != null)
                        collectors.OfClass(typeof(ElementType)).FirstOrDefault(x => x.Name == FamilyFileName);
                    //collectors.FirstOrDefault(x => x.Name == FamilyFileName);

                    ICollection<ElementId> copyIds = new Collection<ElementId>();
                    //FamilySymbol symbol = new FamilySymbol;

                    IList<Element> list = collectors.ToElements();
                    foreach (Element ele in list)
                    {
                        if (ele.Name == FamilyFileName)
                        {
                            copyIds.Add(ele.Id);
                            Transaction trans = new Transaction(doc, "传递单元");
                            trans.Start();
                            //实例化复制粘贴选项,这里实例化就行
                            CopyPasteOptions option = new CopyPasteOptions();
                            //由于材料信息与位移无关,所以位移为null,如果是族实例或者其他与位置有关的,这个地方就需要思考下设置了
                            ElementTransformUtils.CopyElements(docs, copyIds, doc, null, option);
                            trans.Commit();
                            //MessageBox.Show("载入系统族成功");
                            break;
                        }

                    }
                    //保存关闭修改后的文档
                    //doc.Save();
                    docs.Close(false);
                }
            }

            if (LoadButtonCont == "放置")
            {
                try
                {
                    // 放置特殊族
                    if (FamilyFileName == "喷浆护壁" || FamilyFileName == "钢筋挂网")
                    {
                        // 放置喷浆护壁、钢筋挂网等需要根据面新建类型的族
                        Selection selection = uidoc.Selection;
                        Reference ref_face = selection.PickObject(ObjectType.Face, "请选择一个面");
                        PlanarFace planarFace = doc.GetElement(ref_face).GetGeometryObjectFromReference(ref_face) as PlanarFace;
                        // 面积 
                        double areaOfFace = planarFace.Area;
                        // 计算角度和边长
                        CurveLoop loop = planarFace.GetEdgesAsCurveLoops().First();
                        CurveLoopIterator iterator = loop.GetCurveLoopIterator();
                        List<Line> lines = new List<Line>();
                        while (iterator.MoveNext())
                        {
                            Line line = iterator.Current as Line;
                            lines.Add(line);
                        }
                        // 判断是否为四边形
                        if (lines.Count == 4)
                        {
                            // 左角度
                            double triangleOfLeft = lines[0].Direction.AngleTo(lines[1].Direction);
                            // 右角度
                            double triangleOfRight = lines[1].Direction.AngleTo(lines[2].Direction);
                            // 上边长
                            double lengthOfUp = lines[1].Length;
                            // 底边长
                            double lengthOfBottom = lines[3].Length;
                            // 宽 (梯形面积计算公式)
                            double length = (areaOfFace * 2) / (lengthOfUp + lengthOfBottom);
                            // 要复制的族
                            FilteredElementCollector familyCollector = new FilteredElementCollector(doc);
                            family = familyCollector.OfClass(typeof(Family)).FirstOrDefault(x => x.Name == FamilyFileName) as Family;
                            ISet<ElementId> ids = family.GetFamilySymbolIds();
                            // 检查是否已存在
                            string symbolName = FamilyFileName + " " + UnitUtils.Convert(lengthOfBottom, DisplayUnitType.DUT_DECIMAL_FEET, DisplayUnitType.DUT_MILLIMETERS) + "x" + UnitUtils.Convert(length, DisplayUnitType.DUT_DECIMAL_FEET, DisplayUnitType.DUT_MILLIMETERS) + " " + triangleOfLeft * 180 / Math.PI + "° " + triangleOfRight * 180 / Math.PI + "°";
                            FamilySymbol newSymbol = null;
                            foreach (ElementId id in ids)
                            {
                                FamilySymbol fs = doc.GetElement(id) as FamilySymbol;
                                if (fs.Name == symbolName)
                                {
                                    newSymbol = fs;
                                    break;
                                }
                            }
                            // 放置喷浆护壁
                            if (newSymbol == null)
                            {
                                Transaction transaction = new Transaction(doc); //事务
                                transaction.Start("新建族类型");
                                FamilySymbol symbol = doc.GetElement(ids.First()) as FamilySymbol;
                                newSymbol = symbol.Duplicate(symbolName) as FamilySymbol;
                                if (FamilyFileName == "喷浆护壁")
                                {
                                    Parameter leftAngle = newSymbol.LookupParameter("左角");
                                    leftAngle.Set(triangleOfLeft);
                                    Parameter rightAngle = newSymbol.LookupParameter("右角");
                                    rightAngle.Set(triangleOfRight);
                                    Parameter buttomLength = newSymbol.LookupParameter("底部长");
                                    buttomLength.Set(lengthOfBottom);
                                    Parameter width = newSymbol.LookupParameter("宽");
                                    width.Set(length);
                                }
                                if (FamilyFileName == "钢筋挂网")
                                {
                                    Parameter rightAngle = newSymbol.LookupParameter("角度");
                                    rightAngle.Set(triangleOfRight);
                                    Parameter buttomLength = newSymbol.LookupParameter("横向钢筋长");
                                    buttomLength.Set(lengthOfUp);
                                    Parameter width = newSymbol.LookupParameter("宽度");
                                    width.Set(length);
                                }
                                transaction.Commit();
                                uidoc.PromptForFamilyInstancePlacement(newSymbol);
                            }
                            else
                            {
                                uidoc.PromptForFamilyInstancePlacement(newSymbol);
                            }
                        }
                        else
                        {

                            MessageBox.Show("请选择四边形的面", "提示");
                        }

                    }
                    // 放置正常族
                    else
                    {
                        // 放置不需配置参数的族
                        if (FamilyFileCategory == "1" && this.FamilyProperties == null)
                        {
                            // 过滤当前文档是否存在该族
                            FilteredElementCollector collector = new FilteredElementCollector(doc);
                            collector.OfClass(typeof(Family));//.FirstOrDefault(x => x.Name == FamilyFileName);
                            IList<Element> CollectorList = collector.ToElements();

                            foreach (var elem in CollectorList)
                            {
                                var familyItem = elem as Family;
                                // str是要载入族的名称
                                if (familyItem.Name == FamilyFileName)
                                {
                                    family = familyItem;
                                    break;
                                }
                            }

                            var symbol = doc.GetElement(family.GetFamilySymbolIds().First()) as FamilySymbol;
                            //放置可载入族
                            uidoc.PromptForFamilyInstancePlacement(symbol);

                        }
                        // 放置需要配置参数的族
                        else if (FamilyFileCategory == "1" && this.FamilyProperties != null)
                        {
                            // 要复制的族
                            FilteredElementCollector familyCollector = new FilteredElementCollector(doc);
                            family = familyCollector.OfClass(typeof(Family)).FirstOrDefault(x => x.Name == FamilyFileName) as Family;
                            ISet<ElementId> ids = family.GetFamilySymbolIds();
                            FamilySymbol symbol = doc.GetElement(ids.First()) as FamilySymbol;
                            // 复制后的族名称
                            string symbolName = symbol.LookupParameter("项目名称").AsString();
                            foreach (FamilyProperty property in FamilyProperties)
                            {
                                symbolName += "-";
                                symbolName += property.PropertValue;
                            }
                            FamilySymbol newSymbol = null;
                            // 检查是否已存在
                            foreach (ElementId id in ids)
                            {
                                FamilySymbol fs = doc.GetElement(id) as FamilySymbol;
                                if (fs.Name == symbolName)
                                {
                                    newSymbol = fs;
                                    break;
                                }
                            }
                            // 不存在创建
                            if (newSymbol == null)
                            {
                                Transaction transaction = new Transaction(doc); //事务
                                transaction.Start("新建族类型");
                                newSymbol = symbol.Duplicate(symbolName) as FamilySymbol;
                                // 项目特征
                                string xmtz = String.Empty;
                                string ParameterCode = String.Empty;
                                // 设置参数
                                foreach (FamilyProperty familyProperty in FamilyProperties)
                                {
                                    if (!string.IsNullOrEmpty(familyProperty.FamilyPropertyName))
                                    {
                                        Parameter p = newSymbol.LookupParameter(familyProperty.FamilyPropertyName);
                                        if (p.Definition.ParameterType == ParameterType.Length)
                                        {
                                            try
                                            {
                                                double d = Double.Parse(familyProperty.PropertValue);
                                                p.Set(UnitUtils.Convert(d, DisplayUnitType.DUT_MILLIMETERS,
                                                    DisplayUnitType.DUT_DECIMAL_FEET));
                                            }
                                            catch (Exception e)
                                            {
                                                MessageBox.Show(familyProperty.DispalyPropertyName + " 格式错误", "提示");
                                                throw;
                                            }
                                        }
                                        else
                                        {
                                            p.Set(familyProperty.PropertValue);
                                        }
                                    }
                                    // 拼接项目特征、项目编码
                                    xmtz = xmtz + familyProperty.DispalyPropertyName + ":" + familyProperty.PropertValue + "  ";
                                    ParameterCode = ParameterCode + familyProperty.ParameterCode;
                                }
                                // 设置项目特征
                                Parameter xmtzParameter = newSymbol.LookupParameter("项目特征");
                                if (xmtzParameter != null)
                                {
                                    xmtzParameter.Set(xmtz);
                                }
                                // 设置族库编号
                                Parameter zkbhParameter = newSymbol.LookupParameter("族库编号");
                                if (zkbhParameter != null)
                                {
                                    zkbhParameter.Set(ParameterCode);
                                }

                                transaction.Commit();
                                uidoc.PromptForFamilyInstancePlacement(newSymbol);
                            }
                            // 存在直接放置
                            else
                            {
                                uidoc.PromptForFamilyInstancePlacement(newSymbol);
                            }
                        }
                        // 放置系统族
                        else
                        {
                            ElementType targetType = new FilteredElementCollector(doc)
                           .OfClass(typeof(ElementType))
                           .FirstOrDefault(x => x.Name == FamilyFileName) as ElementType;
                            //放置系统族
                            uidoc.PostRequestForElementTypePlacement(targetType);
                        }
                    }
                }
                catch (Exception ex)
                {
                    // user canceled the operation
                    if (!(ex is Autodesk.Revit.Exceptions.OperationCanceledException))
                    {
                        throw ex;
                    }
                }
            }
        }
        //private XYZ PointOfPointToLine(XYZ pointC, XYZ pointA, XYZ pointB)
        //{
        //    Autodesk.Revit.DB.Line ab = Autodesk.Revit.DB.Line.CreateUnbound(pointA, pointB);
        //    //求ab线的单位
        //    XYZ normal = ab.Direction.Normalize();
        //    XYZ dir = new XYZ(0, 0, 1);
        //    //求垂直于ab线的法线
        //    XYZ cross = normal.CrossProduct(dir);

        //    //随意生成该线上的一个点，当成一个虚的d点
        //    Autodesk.Revit.DB.Line cd = Autodesk.Revit.DB.Line.CreateUnbound(pointC, cross);

        //    //求BC与AD的交点
        //    IntersectionResultArray results;
        //    SetComparisonResult result = ab.Intersect(cd, out results);
        //    //重叠，没有重叠就是平行
        //    if (result != SetComparisonResult.Overlap)
        //        return null;
        //    //没有交点或者交点不是1个
        //    if (results == null || results.Size != 1)
        //        return null;
        //    //取得交点
        //    IntersectionResult iResult = results.get_Item(0);
        //    //取得交点坐标
        //    XYZ intersectionPoint = iResult.XYZPoint;
        //    return intersectionPoint;
        //}


        /// <summary>
        /// 求空间某点到线段的垂直交点
        /// </summary>
        /// <param name="pointA">点A</param>
        /// <param name="pointB">点B到点C线段</param>
        /// <param name="pointC">点B到点C线段</param>
        /// <returns></returns>
        private XYZ PointOfPointToLine(XYZ pointA, XYZ pointB, XYZ pointC)
        {
            Line BC = Line.CreateBound(pointB, pointC);
            XYZ normal = BC.Direction.Normalize();
            XYZ dir = XYZ.BasisZ;
            //垂直于BC的法线
            XYZ cross = normal.CrossProduct(dir);
            Line AD = Line.CreateUnbound(pointA, cross);
            //求BC与AD的交点
            IntersectionResultArray results;
            SetComparisonResult result = BC.Intersect(AD, out results);
            //重叠，没有重叠就是平行
            if (result != SetComparisonResult.Overlap)
                return null;
            //没有交点或者交点不是1个
            if (results == null || results.Size != 1)
                return null;
            //取得交点
            IntersectionResult iResult = results.get_Item(0);
            //取得交点坐标
            XYZ intersectionPoint = iResult.XYZPoint;
            return intersectionPoint;
        }

        public string GetName()
        {
            return "LoadFamily";
        }
    }
}